import ij.*;
import ij.process.*;
import ij.gui.*;
import java.awt.*;
import ij.plugin.filter.*;

public class label_particles_ implements PlugInFilter {
	ImagePlus imp;

	public int setup(String arg, ImagePlus imp) {
		this.imp = imp;
		return DOES_8G;
	}
	public void analyse(ImageProcessor ip,int max)
	{
	// this function gives an overview of the number of clusters and the number of clusters with a specified number of pixels
		int w,h,m,maxsize;
		int[] n=new int[max+1];
		w=ip.getWidth();
		h=ip.getHeight();
		for(int j=0;j<h;j++)
			for(int i=0;i<w;i++)		
				n[(int)ip.getPixelValue(i,j)]++;
		m=0;
		maxsize=0;
		for(int i=1;i<max+1;i++)
		{
			if(n[i]>0)
			{
				m++;
				if (n[i]>maxsize) maxsize=n[i];
			}
		}
		IJ.write("There are "+m+" clusters");
		IJ.write("Max cluster size is "+maxsize+" pixels");
		int[]cs=new int[maxsize+1];
		for(int i=1;i<max+1;i++)
		{
				cs[n[i]]++;
		}
		for(int i=1;i<maxsize+1;i++)
			if (cs[i]>0)
				IJ.write(""+cs[i]+" clusters of "+i+" pixels");
	}	
	
	public void change(ImageProcessor ip, int n1, int n2)
	{
// this functions changes all pixels in ip with value n1 to n2
		int i,j,w,h;
		w=ip.getWidth();
		h=ip.getHeight();
		for(j=0;j<h;j++)
			for(i=0;i<w;i++)		
				if(ip.getPixelValue(i,j)==n1) ip.putPixelValue(i,j,n2);
	}			

	public void run(ImageProcessor ip) 
	{
// this function goes over all pixels of a dead pixel map and tries to give each pixel in a cluster of dead pixels a unique number for the cluster.
		int w,h,cnt=0,n;
		ImageProcessor ipnew;
		w=ip.getWidth();
		h=ip.getHeight();
		ipnew=new ShortProcessor(w,h);
// if a dead pixel is adjacent to another dead pixel, it receives the same cluster number, otherwise it receives a new cluster number
//we scan the image row by row --> check whether the adjacent pixels left, left-above and above are dead

		//top left corner i=0; j=0
		if (ip.getPixelValue(0,0)>0) {cnt++; ipnew.putPixelValue(0,0,cnt);}

		//upper edge j=0
		for(int i=1;i<w;i++)
			if(ip.getPixelValue(i,0)>0)
				if (ip.getPixelValue(i-1,0)>0) 
					ip.putPixelValue(i,0,ipnew.getPixelValue(i-1,0));
				else {cnt++;ipnew.putPixelValue(i,0,cnt);}
		
		//left edge i=0
		for(int j=1;j<h;j++)
			if(ip.getPixelValue(0,j)>0)
				if (ip.getPixelValue(0,j-1)>0) 
					ipnew.putPixelValue(0,j,ipnew.getPixelValue(0,j-1));
				else {cnt++;ipnew.putPixelValue(0,j,cnt);}
					
		//free standing pixels
		for(int j=1;j<h;j++)
			for(int i=1;i<w;i++)
				if(ip.getPixelValue(i,j)>0)
				{
					if((i>0)&&(j>0)) 
					{	if(ip.getPixelValue(i-1,j-1)>0) ipnew.putPixelValue(i,j,ipnew.getPixelValue(i-1,j-1));
						else if (ip.getPixelValue(i-1,j)>0) ipnew.putPixelValue(i,j,ipnew.getPixelValue(i-1,j));
						else if (ip.getPixelValue(i,j-1)>0) ipnew.putPixelValue(i,j,ipnew.getPixelValue(i,j-1));
						else {cnt++;ipnew.putPixelValue(i,j,cnt);}
					}
				
				}

		boolean changed=false;
//numbering of dead clusters could fail when a dead pixel has an adjacent dead cluster right above...

		for(int j=1;j<h;j++)
			for(int i=0;i<w;i++)
				if(ipnew.getPixelValue(i,j)>0)
					if((ipnew.getPixelValue(i,j-1)>0)&&(ipnew.getPixelValue(i,j)!=ipnew.getPixelValue(i,j-1)))
					{
						change(ipnew,(int)ipnew.getPixelValue(i,j-1),(int)ipnew.getPixelValue(i,j)); changed=true;
					}
		
		
		analyse(ipnew,cnt);

		ImagePlus impnew=new ImagePlus(imp.getTitle()+" analysed",ipnew);
		impnew.show();
	}

}
